AnyDAC: First impressions
Over the last few days, when I’ve had some free time available, I’ve been working with AnyDAC’s TADMemTable, which Dimitry Arafiev, the author, pitched to me as a replacement for and an improvement upon TClientDataset. I’d like to report on how smoothly everything went and how well it works, and spend some time on my experience with the dataset and the new features it brings to the table.
Unfortunately, I don’t always get what I’d like. I can’t really talk about stuff like that because I haven’t reached that point yet, due to various bugs and other implementation hurdles.
The installation and setup phase went quite well, actually. The package was a 19 MB installer including full source code, DPKs and other requisite files for building the AnyDAC packages under anything from Delphi 5/C++ Builder 5 to RAD Studio 2010 (or FPC 2.2.x), a nice big helpfile and a fairly comprehensive Samples folder. The download was nice and fast, and the only real annoyance was the installer getting a few paths wrong. The helpfile is quite well-written in good, understandible English, which is good to see; that’s not always the case when working with libraries written by people from non-English-speaking countries.
I loaded up the TURBU project, backed up everything to source control, and went into dm_database.pas, where I keep my client datasets. Time for the trial by fire: Open the form designer, switch to text view, Select All, SyncEdit, replace all “TClientDataset” with “TADMemTable”, switch back to form view. IMO, if something is presented as a replacement for something else, you ought to be able to swap it out and have it “just work.” In practice, it’s rarely that simple.
TADMemDataset has the same support for filtering as TClientDatset, and it has a CloneCursor function, which is good because I use it pretty extensively. What it doesn’t have, though, is the same public interface as TClientDataset. For example, TClientDataset has a property called LogChanges, where if you turn it on it will save all edits to an intermediary datastore instead of the main one until you call MergeChangeLog or CancelUpdates. Among other things, this makes implementing an editor dialog with Apply and Cancel buttons very simple. TADMemDataset supports the same functionality, but the property that controls it is called CachedUpdates, not LogChanges, and to merge the change log you call CommitUpdates.
I got a bit of a rude surprise when I tried to convert one of my ClientDatasets to a TADMemTable: it didn’t like one of the fields. The field was a TSingleField, and the internal storage table doesn’t know what a Single is, so it converts it to a Double, which causes errors when trying to open the dataset. When I reported this to Dimitry, he replied that “ftSingle is not supported for a while.”
Also, using custom filtering with the OnFilterRecord event handler seems to break CloneCursor. It looks like an order-of-operations issue inside TADDataset.InternalOpen: X needs to happen before Y, which needs to happen before Z, which is the way it’s currently set up, except that Z and Y both need to happen before X if you’re cloning a dataset with an OnFilterRecord event handler. Apparently this is because X is doing too many different things, and needs to be reworked a bit.
I’ve reported all these issues to Dimitry and he says he’ll get a fixed version to me as soon as possible. What I’ve seen so far of the dataset’s API looks interesting, but it’s kind of difficult to test for the moment, until the rough edges are polished. I’ll post another update once I’m able to.
One other strange thing: In order to use the dataset, it requires access to some interface that has to be initialized by dropping a certain component onto your project that seems to have no other purpose except to make this interface available. (Sorta like the XP Manifest component that does nothing except link a resource into your EXE.) I’m not quite sure why TADMemTable can’t manage its own dependencies, but that’s kind of disappointing. Hopefully that will get fixed in an update.